home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / ACCUM.C next >
Encoding:
C/C++ Source or Header  |  1998-07-26  |  9.8 KB  |  363 lines

  1. /* $Id: accum.c,v 3.2 1998/07/17 03:26:09 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: accum.c,v $
  26.  * Revision 3.2  1998/07/17 03:26:09  brianp
  27.  * include masking.h
  28.  *
  29.  * Revision 3.1  1998/06/30 04:08:47  brianp
  30.  * glAccum(GL_RETURN, s) didn't obey glColorMask() settings
  31.  *
  32.  * Revision 3.0  1998/01/31 20:46:29  brianp
  33.  * initial rev
  34.  *
  35.  */
  36.  
  37.  
  38. #ifdef PC_HEADER
  39. #include "all.h"
  40. #else
  41. #include <limits.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include "accum.h"
  45. #include "context.h"
  46. #include "macros.h"
  47. #include "masking.h"
  48. #include "span.h"
  49. #include "types.h"
  50. #endif
  51.  
  52.  
  53. void gl_alloc_accum_buffer( GLcontext *ctx )
  54. {
  55.    GLint n;
  56.  
  57.    if (ctx->Buffer->Accum) {
  58.       free( ctx->Buffer->Accum );
  59.       ctx->Buffer->Accum = NULL;
  60.    }
  61.  
  62.    /* allocate accumulation buffer if not already present */
  63.    n = ctx->Buffer->Width * ctx->Buffer->Height * 4 * sizeof(GLaccum);
  64.    ctx->Buffer->Accum = (GLaccum *) malloc( n );
  65.    if (!ctx->Buffer->Accum) {
  66.       /* unable to setup accumulation buffer */
  67.       gl_error( ctx, GL_OUT_OF_MEMORY, "glAccum" );
  68.    }
  69. }
  70.  
  71.  
  72.  
  73. void gl_ClearAccum( GLcontext *ctx,
  74.                     GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
  75. {
  76.    if (INSIDE_BEGIN_END(ctx)) {
  77.       gl_error( ctx, GL_INVALID_OPERATION, "glAccum" );
  78.       return;
  79.    }
  80.    ctx->Accum.ClearColor[0] = CLAMP( red, -1.0, 1.0 );
  81.    ctx->Accum.ClearColor[1] = CLAMP( green, -1.0, 1.0 );
  82.    ctx->Accum.ClearColor[2] = CLAMP( blue, -1.0, 1.0 );
  83.    ctx->Accum.ClearColor[3] = CLAMP( alpha, -1.0, 1.0 );
  84. }
  85.  
  86.  
  87.  
  88.  
  89. void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
  90. {
  91.    GLuint xpos, ypos, width, height;
  92.    GLfloat acc_scale;
  93.  
  94.    if (INSIDE_BEGIN_END(ctx)) {
  95.       gl_error( ctx, GL_INVALID_OPERATION, "glAccum" );
  96.       return;
  97.    }
  98.  
  99.    if (ctx->Visual->AccumBits==0 || !ctx->Buffer->Accum) {
  100.       /* No accumulation buffer! */
  101.       gl_warning(ctx, "Calling glAccum() without an accumulation buffer");
  102.       return;
  103.    }
  104.  
  105.    if (sizeof(GLaccum)==1) {
  106.       acc_scale = 127.0;
  107.    }
  108.    else if (sizeof(GLaccum)==2) {
  109.       acc_scale = 32767.0;
  110.    }
  111.    else {
  112.       /* sizeof(GLaccum) > 2 (Cray) */
  113.       acc_scale = (float) SHRT_MAX;
  114.    }
  115.  
  116.    if (ctx->NewState)
  117.       gl_update_state( ctx );
  118.  
  119.    /* Determine region to operate upon. */
  120.    if (ctx->Scissor.Enabled) {
  121.       xpos = ctx->Scissor.X;
  122.       ypos = ctx->Scissor.Y;
  123.       width = ctx->Scissor.Width;
  124.       height = ctx->Scissor.Height;
  125.    }
  126.    else {
  127.       /* whole window */
  128.       xpos = 0;
  129.       ypos = 0;
  130.       width = ctx->Buffer->Width;
  131.       height = ctx->Buffer->Height;
  132.    }
  133.  
  134.    switch (op) {
  135.       case GL_ADD:
  136.          {
  137.         GLaccum ival, *acc;
  138.         GLuint i, j;
  139.  
  140.         ival = (GLaccum) (value * acc_scale);
  141.         for (j=0;j<height;j++) {
  142.            acc = ctx->Buffer->Accum
  143.                      + (ypos * ctx->Buffer->Width + xpos) * 4;
  144.            for (i=0;i<width;i++) {
  145.           *acc += ival;      acc++;   /* red */
  146.           *acc += ival;      acc++;   /* green */
  147.           *acc += ival;      acc++;   /* blue */
  148.           *acc += ival;      acc++;   /* alpha */
  149.            }
  150.            ypos++;
  151.         }
  152.      }
  153.      break;
  154.       case GL_MULT:
  155.      {
  156.         GLaccum *acc;
  157.         GLuint i, j;
  158.  
  159.         for (j=0;j<height;j++) {
  160.            acc = ctx->Buffer->Accum
  161.                      + (ypos * ctx->Buffer->Width + xpos) * 4;
  162.            for (i=0;i<width;i++) {
  163.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*r*/
  164.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*g*/
  165.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*g*/
  166.           *acc = (GLaccum) ( (GLfloat) *acc * value );      acc++; /*a*/
  167.            }
  168.            ypos++;
  169.         }
  170.      }
  171.      break;
  172.       case GL_ACCUM:
  173.      {
  174.         GLaccum *acc;
  175.         GLubyte rgba[MAX_WIDTH][4];
  176.         GLfloat rscale, gscale, bscale, ascale;
  177.         GLuint i, j;
  178.  
  179.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  180.  
  181.         /* Accumulate */
  182.         rscale = value * acc_scale / 255.0;
  183.         gscale = value * acc_scale / 255.0;
  184.         bscale = value * acc_scale / 255.0;
  185.         ascale = value * acc_scale / 255.0;
  186.         for (j=0;j<height;j++) {
  187.                gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
  188.            acc = ctx->Buffer->Accum
  189.                      + (ypos * ctx->Buffer->Width + xpos) * 4;
  190.            for (i=0;i<width;i++) {
  191.           *acc += (GLaccum) ( (GLfloat) rgba[i][RCOMP] * rscale );  acc++;
  192.           *acc += (GLaccum) ( (GLfloat) rgba[i][GCOMP] * gscale );  acc++;
  193.           *acc += (GLaccum) ( (GLfloat) rgba[i][BCOMP] * bscale );  acc++;
  194.           *acc += (GLaccum) ( (GLfloat) rgba[i][ACOMP] * ascale );  acc++;
  195.            }
  196.            ypos++;
  197.         }
  198.  
  199.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  200.      }
  201.      break;
  202.       case GL_LOAD:
  203.      {
  204.         GLaccum *acc;
  205.         GLubyte rgba[MAX_WIDTH][4];
  206.         GLfloat rscale, gscale, bscale, ascale;
  207.         GLuint i, j;
  208.  
  209.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
  210.  
  211.         /* Load accumulation buffer */
  212.         rscale = value * acc_scale / 255.0;
  213.         gscale = value * acc_scale / 255.0;
  214.         bscale = value * acc_scale / 255.0;
  215.         ascale = value * acc_scale / 255.0;
  216.         for (j=0;j<height;j++) {
  217.                gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
  218.            acc = ctx->Buffer->Accum
  219.                      + (ypos * ctx->Buffer->Width + xpos) * 4;
  220.            for (i=0;i<width;i++) {
  221.           *acc++ = (GLaccum) ( (GLfloat) rgba[i][RCOMP] * rscale );
  222.           *acc++ = (GLaccum) ( (GLfloat) rgba[i][GCOMP] * gscale );
  223.           *acc++ = (GLaccum) ( (GLfloat) rgba[i][BCOMP] * bscale );
  224.           *acc++ = (GLaccum) ( (GLfloat) rgba[i][ACOMP] * ascale );
  225.            }
  226.            ypos++;
  227.         }
  228.  
  229.         (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
  230.      }
  231.      break;
  232.       case GL_RETURN:
  233.      {
  234.         GLubyte rgba[MAX_WIDTH][4];
  235.         GLaccum *acc;
  236.         GLfloat rscale, gscale, bscale, ascale;
  237.         GLuint i, j;
  238.  
  239.         rscale = value / acc_scale * 255.0F;
  240.         gscale = value / acc_scale * 255.0F;
  241.         bscale = value / acc_scale * 255.0F;
  242.         ascale = value / acc_scale * 255.0F;
  243.         for (j=0;j<height;j++) {
  244.            acc = ctx->Buffer->Accum
  245.                      + (ypos * ctx->Buffer->Width + xpos) * 4;
  246.            for (i=0;i<width;i++) {
  247.           GLint r, g, b, a;
  248.           r = (GLint) ( (GLfloat) (*acc++) * rscale + 0.5F );
  249.           g = (GLint) ( (GLfloat) (*acc++) * gscale + 0.5F );
  250.           b = (GLint) ( (GLfloat) (*acc++) * bscale + 0.5F );
  251.           a = (GLint) ( (GLfloat) (*acc++) * ascale + 0.5F );
  252.           rgba[i][RCOMP] = CLAMP( r, 0, 255 );
  253.           rgba[i][GCOMP] = CLAMP( g, 0, 255 );
  254.           rgba[i][BCOMP] = CLAMP( b, 0, 255 );
  255.           rgba[i][ACOMP] = CLAMP( a, 0, 255 );
  256.            }
  257.                if (ctx->Color.SWmasking) {
  258.                   gl_mask_rgba_span( ctx, width, xpos, ypos, rgba );
  259.                }
  260.                (*ctx->Driver.WriteRGBASpan)( ctx, width, xpos, ypos, rgba, NULL );
  261.            ypos++;
  262.         }
  263.      }
  264.      break;
  265.       default:
  266.          gl_error( ctx, GL_INVALID_ENUM, "glAccum" );
  267.    }
  268. }
  269.  
  270.  
  271.  
  272.  
  273. /*
  274.  * Clear the accumulation Buffer->
  275.  */
  276. void gl_clear_accum_buffer( GLcontext *ctx )
  277. {
  278.    GLuint buffersize;
  279.    GLfloat acc_scale;
  280.  
  281.    if (ctx->Visual->AccumBits==0) {
  282.       /* No accumulation buffer! */
  283.       return;
  284.    }
  285.  
  286.    if (sizeof(GLaccum)==1) {
  287.       acc_scale = 127.0;
  288.    }
  289.    else if (sizeof(GLaccum)==2) {
  290.       acc_scale = 32767.0;
  291.    }
  292.    else {
  293.       /* sizeof(GLaccum) > 2 (Cray) */
  294.       acc_scale = (float) SHRT_MAX;
  295.    }
  296.  
  297.    /* number of pixels */
  298.    buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
  299.  
  300.    if (!ctx->Buffer->Accum) {
  301.       /* try to alloc accumulation buffer */
  302.       ctx->Buffer->Accum = (GLaccum *)
  303.                        malloc( buffersize * 4 * sizeof(GLaccum) );
  304.    }
  305.  
  306.    if (ctx->Buffer->Accum) {
  307.       if (ctx->Scissor.Enabled) {
  308.      /* Limit clear to scissor box */
  309.      GLaccum r, g, b, a;
  310.      GLint i, j;
  311.          GLint width, height;
  312.          GLaccum *row;
  313.      r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
  314.      g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
  315.      b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
  316.      a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
  317.          /* size of region to clear */
  318.          width = 4 * (ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1);
  319.          height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
  320.          /* ptr to first element to clear */
  321.          row = ctx->Buffer->Accum
  322.                + 4 * (ctx->Buffer->Ymin * ctx->Buffer->Width
  323.                       + ctx->Buffer->Xmin);
  324.          for (j=0;j<height;j++) {
  325.             for (i=0;i<width;i+=4) {
  326.                row[i+0] = r;
  327.                row[i+1] = g;
  328.                row[i+2] = b;
  329.                row[i+3] = a;
  330.         }
  331.             row += 4 * ctx->Buffer->Width;
  332.      }
  333.       }
  334.       else {
  335.      /* clear whole buffer */
  336.      if (ctx->Accum.ClearColor[0]==0.0 &&
  337.          ctx->Accum.ClearColor[1]==0.0 &&
  338.          ctx->Accum.ClearColor[2]==0.0 &&
  339.          ctx->Accum.ClearColor[3]==0.0) {
  340.         /* Black */
  341.         MEMSET( ctx->Buffer->Accum, 0, buffersize * 4 * sizeof(GLaccum) );
  342.      }
  343.      else {
  344.         /* Not black */
  345.         GLaccum *acc, r, g, b, a;
  346.         GLuint i;
  347.  
  348.         acc = ctx->Buffer->Accum;
  349.         r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
  350.         g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
  351.         b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
  352.         a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
  353.         for (i=0;i<buffersize;i++) {
  354.            *acc++ = r;
  355.            *acc++ = g;
  356.            *acc++ = b;
  357.            *acc++ = a;
  358.         }
  359.      }
  360.       }
  361.    }
  362. }
  363.